/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2017-2023. All rights reserved.
 * Description: ai stats log builder class
 */

#include "infra/om/stats/ai_stats_log_builder.h"

#include <sstream>

#include "infra/base/api_export.h"
#include "infra/om/stats/ai_stats_log_utils.h"
#include "infra/om/stats/ai_stats_log_manager.h"

namespace hiai {
AiStatsLogBuilder& AiStatsLogBuilder::CallUid(unsigned int uid)
{
    this->statsData_.callPkg = static_cast<int>(uid);
    return *this;
}

AiStatsLogBuilder& AiStatsLogBuilder::CallTimeNow()
{
    this->statsData_.callTime = AiStatsTime::TimeNow();
    return *this;
}

AiStatsLogBuilder& AiStatsLogBuilder::SetCallTime(uint64_t callTime)
{
    this->statsData_.callTime = callTime;
    return *this;
}

AiStatsLogBuilder& AiStatsLogBuilder::SetEngineType(AiStatsEngineType engineType)
{
    this->statsData_.engineType = engineType;
    return *this;
}

AiStatsLogBuilder& AiStatsLogBuilder::InterfaceName(const char* clientInterfaceName)
{
    this->statsData_.interfaceName = clientInterfaceName;
    return *this;
}

AiStatsLogBuilder& AiStatsLogBuilder::ProcessResult(int result)
{
    // add count for return,build only for a group data
    this->statsData_.result.insert(std::pair<int, int>(result, 1));
    this->statsData_.allCnt = 1;
    // is fail for interface_function
    this->statsData_.failCnt = (result != 0) ? 1 : 0;
    return *this;
}
AiStatsLogBuilder& AiStatsLogBuilder::RunTime()
{
    this->statsData_.runTime = this->time_.GetRunTime();
    return *this;
}

AiStatsLogBuilder& AiStatsLogBuilder::StartProcess()
{
    this->time_.StartProcess();
    return *this;
}
AiStatsLogBuilder& AiStatsLogBuilder::EndProcess()
{
    this->time_.EndProcess();
    return *this;
}

AiStatsLogBuilder& AiStatsLogBuilder::SetProcessName(const char* processName)
{
    this->statsData_.processName = processName;
    return *this;
}

AiStatsLogBuilder& AiStatsLogBuilder::SetDdkVersion(const char* ddkVersion)
{
    if (ddkVersion == nullptr) {
        this->statsData_.ddkVersion = "";
    } else {
        this->statsData_.ddkVersion = ddkVersion;
    }
    return *this;
}

bool AiStatsLogBuilder::CheckStatus(AiStatsEngineType engineType)
{
#if defined(STATS_CLIENT)
    (void)engineType;
    return true;
#else
    std::map<AiStatsEngineType, std::atomic<bool>>::const_iterator iter =
        AiStatsLogCfgUtils::isMMLogSwitchOpen_.find(engineType);
    if (iter == AiStatsLogCfgUtils::isMMLogSwitchOpen_.end() || !iter->second) {
        return false;
    }
    return true;
#endif
}

void AiStatsLogBuilder::Build()
{
    AiStatsLogWriter* writer = nullptr;
    switch (statsData_.engineType) {
        case AI_STATS_HIAI_MNGR:
            writer = AiMMStatsLogWriter::GetInstance();
            break;
        case AI_STATS_HIAI_ENGINE:
            writer = AiHiAiEngineStatsLogWriter::GetInstance();
            break;
        case AI_STATS_ANN:
            writer = AiANNStatsLogWriter::GetInstance();
            break;
        case AI_STATS_HIAI_HCS:
            writer = AiHiAiHCSStatsLogWriter::GetInstance();
            break;
        case AI_STATS_HIAI_DDK:
            writer = AiHiAiDDKStatsLogWriter::GetInstance();
            break;
        default:
            break;
    }
    if (writer != nullptr) {
        writer->Write(statsData_);
    }
}

INFRA_API_EXPORT AiStatsLogBuilder& AiStatsLogBuilder::StartStats(
    unsigned int uid, AiStatsEngineType engineType, const char* clientInterfaceName, const char* processName)
{
    this->SetEngineType(engineType);
    if (!CheckStatus(engineType)) {
        return *this;
    }
    this->CallTimeNow();
    this->CallUid(uid);
    this->InterfaceName(clientInterfaceName);
    this->StartProcess();
    this->SetProcessName(processName);
    return *this;
}

INFRA_API_EXPORT void AiStatsLogBuilder::EndStats(int result)
{
    if (!CheckStatus(this->statsData_.engineType)) {
        return;
    }
    this->EndProcess();
    this->ProcessResult(result);
    this->RunTime();
    this->Build();
}
// 打点函数为一次性行为，处理时间基本为零，使用此函数进行打点
INFRA_API_EXPORT void AiStatsLogBuilder::Stats(unsigned int uid, AiStatsEngineType engineType,
    const char* clientInterfaceName, const char* processName, int result)
{
    if (!CheckStatus(engineType)) {
        return;
    }
    this->SetEngineType(engineType);
    this->CallTimeNow();
    this->CallUid(uid);
    this->InterfaceName(clientInterfaceName);
    this->SetProcessName(processName);
    this->ProcessResult(result);
    // no Time
    this->statsData_.runTime = 0;
    this->Build();
}

INFRA_API_EXPORT void AiStatsLogBuilder::Stats(unsigned int uid, AiStatsEngineType engineType,
    const char* clientInterfaceName, const char* processName, const char* ddkVersion, int result)
{
    if (!CheckStatus(engineType)) {
        return;
    }
    this->SetEngineType(engineType);
    this->CallTimeNow();
    this->CallUid(uid);
    this->InterfaceName(clientInterfaceName);
    this->SetProcessName(processName);
    this->SetDdkVersion(ddkVersion);
    this->ProcessResult(result);
    // no Time
    this->statsData_.runTime = 0;
    this->Build();
}

INFRA_API_EXPORT void AiStatsLogBuilder::Stats(unsigned int uid, AiStatsEngineType engineType,
    const char* clientInterfaceName, const char* processName, const char* ddkVersion, int result, int runTime,
    uint64_t callTime)
{
    if (!CheckStatus(engineType)) {
        return;
    }
    this->SetEngineType(engineType);
    this->SetCallTime(callTime);
    this->CallUid(uid);
    this->InterfaceName(clientInterfaceName);
    this->SetProcessName(processName);
    this->ProcessResult(result);
    this->SetDdkVersion(ddkVersion);
    this->statsData_.runTime = runTime;
    this->Build();
}
} // end namespace ai
